home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / umich / network / ka9q / nhclb120.zoo / plus.c < prev    next >
C/C++ Source or Header  |  1992-02-11  |  13KB  |  619 lines

  1. /* OS- and machine-dependent stuff for HP 110+ running MS-DOS */
  2. #if defined(__TURBOC__)
  3. #pragma inline
  4. #include <stdio.h>
  5. #include "config.h"
  6. #if defined(PLUS)
  7. #include "global.h"
  8. #include "8250.h"
  9. #include "asy.h"
  10. #include "plus.h"
  11. #include "iface.h"
  12.  
  13. struct asy asy[ASY_MAX];
  14. unsigned nasy;
  15. byte model;
  16.  
  17. void    _Cdecl    __int__        (int interruptnum);
  18. void    interrupt     (* _Cdecl getvect(int interruptno)) ();
  19. #define geninterrupt(i) __int__(i)
  20.  
  21. extern unsigned char intstk[];
  22. extern unsigned int sssave, spsave;
  23. /*
  24.  =================================================================
  25.  */
  26. int16 modemdev, serialdev;
  27. struct plusasy plusasy[ASY_MAX];
  28. /* ASY interrupt handlers */
  29. byte modemconfig, serialconfig;
  30. extern void interrupt plustxsvec();
  31. extern void interrupt plusrxsvec();
  32. extern void interrupt plustxmvec();
  33. extern void interrupt plusrxmvec();
  34. byte *com1_name="COM1";         /* file to open  for serial            */
  35. byte *com3_name="COM3";         /* file to open for modem            */
  36. int com1handle;            /* file handle saved here            */
  37. int com3handle;            /* file handle saved here            */
  38. byte *ioctlon1="M1;";           /* IOCTL to turn on  serial port            */
  39. byte *ioctloff1="M3;";          /* IOCTL to turn off serial port            */
  40. byte *ioctlon3="M4;";           /* IOCTL to turn on  modem port            */
  41. byte *ioctloff3="M5;";          /* IOCTL to turn off modem port            */
  42.  
  43. /* Initialize asynch port "dev" */
  44. int
  45. asy_init(dev,arg1,arg2,bufsize)
  46. int16 dev;
  47. char *arg1,*arg2;
  48. unsigned bufsize;
  49. {
  50.     register unsigned base;
  51.     register struct fifo *fp;
  52.     register struct asy *ap;
  53.   
  54.     ap = &asy[dev];
  55.     ap->addr = htoi(arg1);
  56.     ap->vec = htoi(arg2);
  57.     /* Set up receiver FIFO */
  58.     fp = &ap->fifo;
  59.     if((fp->buf = malloc(bufsize)) == NULLCHAR){
  60.         printf("asy%d: No space for rx buffer\r\n");
  61.         fflush(stdout);
  62.         return;
  63.     }
  64.     fp->bufsize = bufsize;
  65.     fp->wp = fp->rp = fp->buf;
  66.     fp->cnt = 0;
  67.   
  68.     base = ap->addr;
  69.     /* Purge the receive data buffer
  70.      * Set line control register: 8 bits, no parity
  71.      *
  72.      * Turn on receive interrupt enable, leave transmit
  73.      * interrupts turned off for now
  74.      *
  75.      * Set modem control register: assert DTR, RTS, turn on serial
  76.      * port
  77.      *
  78.      * Enable rx interrupt
  79.      */
  80.     (void)init_com(dev,'N',1);
  81.     /*
  82.      * set calibration in delay
  83.      */
  84.      /*
  85.       * turn off lousy beeper on ring interrupts.
  86.       */
  87.      _AL=2;
  88.      __int__(0x59);
  89.     /* Set interrupt vector to SIO handler
  90.      *  DON'T bump them by 8 as we use the actual
  91.      *  interrupt numbers, not the number -8 as in
  92.      *  the pc asy entry.
  93.      *
  94.      *  If the computer is a portable only the serial interrupts are used
  95.      *  If the computer is a P+ both serial and modem interrupts are used
  96.      *
  97.      *                     110    110p serial   110p modem
  98.      *          rx vector  0x4f       0x4f       0x4e
  99.      *          tx vector  0x4a       0x4a       0x40
  100.      *          base addr  0xa4       0x44         0xa4   
  101.      *
  102.      */
  103.     if(base==0x44 || model==1) {
  104.     plusasy[dev].oldrx=getvect(0x4f);
  105.     plusasy[dev].oldtx=getvect(0x4a);
  106.     if(model==1) {
  107.         asy[dev].addr=0xa4;
  108.             setvect(0x4a,plustxmvec);
  109.             setvect(0x4f,plusrxmvec);
  110.         modemdev=dev;
  111.     }
  112.     else {
  113.         setvect(0x4a,plustxsvec);
  114.         setvect(0x4f,plusrxsvec);
  115.         serialdev=dev;
  116.     }
  117.     }
  118.     else { /* address not 0x44 and not a portable, must be plus modem */
  119.     plusasy[dev].oldrx=getvect(0x4e);
  120.     plusasy[dev].oldtx=getvect(0x40);
  121.     setvect(0x40,plustxmvec);
  122.     setvect(0x4e,plusrxmvec);
  123.     modemdev=dev;
  124.     }
  125. } /* asy_init */
  126.  
  127. int
  128. asy_stop(iface)
  129. struct interface *iface;
  130. {
  131.     register unsigned base;
  132.     register struct asy *ap;
  133.   
  134.     ap = &asy[iface->dev];
  135.     base = ap->addr;
  136.   
  137. /*
  138.  * hardware ints off
  139.  */
  140.     outportb(base+INTRCONTROL,(unsigned char)0xf0);
  141. /*
  142.  * turn off power to the serial port and
  143.  * Restore original interrupt vectors
  144.  */
  145.     if(base==0x44 || model==1) {
  146.         serial_power(0);
  147.         setvect(0x4f,plusasy[iface->dev].oldrx);
  148.         setvect(0x4a,plusasy[iface->dev].oldtx);
  149.     }
  150.     else {
  151.         modem_power(0);
  152.         setvect(0x4e,plusasy[iface->dev].oldrx);
  153.         setvect(0x40,plusasy[iface->dev].oldtx);
  154.     }
  155.     return(0);
  156. }
  157.  
  158. /* Asynchronous line I/O control */
  159. asy_ioctl(interface,argc,argv)
  160. struct interface *interface;
  161. int argc;
  162. char *argv[];
  163. {
  164.     if(argc < 1){
  165.         printf("%d\r\n",asy[interface->dev].speed);
  166.         return 0;
  167.     }
  168.     return asy_speed(interface->dev,atoi(argv[0]));
  169. }
  170.  
  171. /* Set asynch line speed */
  172. int
  173. asy_speed(dev,speed)
  174. int16 dev;
  175. int speed;
  176. {
  177.     register unsigned base;
  178.     register int divisor;
  179.     char i_state;
  180.   
  181.     if(speed == 0 || dev >= nasy)
  182.         return;
  183.   
  184.     base = asy[dev].addr;
  185.     asy[dev].speed = speed;
  186. /*
  187.  *  Setup baud rate
  188.  */
  189.     divisor=1333500L/speed - 1;
  190.     i_state = disable();
  191.     outportb((unsigned)(base+BAUDLO), (unsigned char)(divisor));
  192.     outportb((unsigned)(base+BAUDHI), (unsigned char)(divisor>>8));
  193.     restore(i_state);
  194. }
  195.  
  196. /* Send a buffer to serial transmitter */
  197. asy_output(dev,buf,cnt)
  198. unsigned dev;
  199. char *buf;
  200. unsigned short cnt;
  201. {
  202.     register struct dma *dp;
  203.     unsigned base;
  204.     char i_state;
  205.  
  206.     if(cnt == 0)
  207.     return;
  208.     if(dev >= nasy)
  209.         return;
  210.     base = asy[dev].addr;
  211.     dp = &asy[dev].dma;
  212.     i_state = disable();
  213.     if(dp->flags){
  214.         restore(i_state);
  215.         return; /* Already busy */
  216.     }
  217.     dp->data = buf;
  218.     dp->cnt = cnt;
  219.     dp->flags = 1;
  220.     /* Enable transmitter buffer empty interrupt and simulate
  221.      * an interrupt; this will get things rolling.
  222.      */
  223.     clrbit(base+INTRCONTROL,0x80);
  224.     setbit(base+INTRCONTROL,0x40);
  225.     asytxint(dev);
  226.     restore(i_state);
  227. }
  228.  
  229. /* Receive characters from asynch line
  230.  * Returns count of characters read
  231.  */
  232. int16
  233. asy_recv(dev,buf,cnt)
  234. int16 dev;
  235. char *buf;
  236. unsigned cnt;
  237. {
  238.     unsigned tot,n;
  239.     int kbread();
  240.     char i_state;
  241.     struct fifo *fp;
  242.   
  243.     fp = &asy[dev].fifo;
  244.     tot = 0;
  245.     /* Read from serial I/O input buffer */
  246.     i_state = disable();
  247.     for(;;){
  248.         n = min(cnt,fp->cnt);
  249.         if(n == 0)
  250.             break;
  251.         n = min(n,&fp->buf[fp->bufsize] - fp->rp);
  252.         memcpy(buf,fp->rp,n);
  253.         fp->rp += n;
  254.         if(fp->rp >= &fp->buf[fp->bufsize])
  255.             fp->rp = fp->buf;
  256.         fp->cnt -= n;
  257.         buf += n;
  258.         tot += n;
  259.         cnt -= n;
  260.     }
  261.     restore(i_state);
  262.     return tot;
  263.   
  264. }
  265.  
  266. /* Process 110P receiver interrupts */
  267. static
  268. asyrxint(dev)
  269. unsigned dev;
  270. {
  271.     unsigned base;
  272.     register struct fifo *fp;
  273.     char c;
  274.   
  275.     base = asy[dev].addr;
  276.     fp = &asy[dev].fifo;
  277.     c = inportb(base+RXDATA);
  278.     /* Process incoming data;
  279.      * If buffer is full, we have no choice but
  280.      * to drop the character
  281.      */
  282.     if(fp->cnt != fp->bufsize){
  283.         *fp->wp++ = c;
  284.         if(fp->wp == &fp->buf[fp->bufsize])
  285.             /* Wrap around */
  286.             fp->wp = fp->buf;
  287.         fp->cnt++;
  288.     }
  289. }
  290.  
  291. /* Handle 110P transmitter interrupts */
  292. static
  293. asytxint(dev)
  294. unsigned dev;
  295. {
  296.     register struct dma *dp;
  297.     register unsigned base;
  298.   
  299.     base = asy[dev].addr;
  300.     dp = &asy[dev].dma;
  301.     if(!dp->flags){
  302.         /* "Shouldn't happen", but disable transmit
  303.          * interrupts anyway
  304.          */
  305.     setbit(base+INTRCONTROL,0xc0);
  306.     return; /* Nothing to send */
  307.     }
  308.     while(inportb(base+STATUS) & 0x02){
  309.         outportb(base+TXDATA,*dp->data++);
  310.         if(--dp->cnt == 0){
  311.             dp->flags = 0;
  312.             /* Disable transmit interrupts */
  313.             setbit(base+INTRCONTROL,0xc0);
  314.             break;
  315.     }
  316. /*
  317.  * turn em back on, we got more to do
  318.  */
  319.         clrbit(base+INTRCONTROL,0x80);
  320.         setbit(base+INTRCONTROL,0x40);
  321.     }
  322. }
  323.  
  324. int
  325. stxrdy(dev)
  326. int16 dev;
  327. {
  328.     return(!asy[dev].dma.flags);
  329. }
  330. /* Set bit(s) in I/O port */
  331.   
  332. setbit(port,bits)
  333. unsigned port;
  334. char bits;
  335. {
  336.     outportb(port,(char)inportb(port)|bits);
  337. }
  338.  
  339. /* Clear bit(s) in I/O port */
  340. clrbit(port,bits)
  341. unsigned port;
  342. char bits;
  343. {
  344.     outportb(port,(char)(inportb(port) & ~bits));
  345. }
  346.  
  347. int init_com(dev,wordlen,parity)
  348. int dev, wordlen;
  349. char parity;
  350. {
  351.     int i, offset, sconfig;
  352.     i=peek(0xffff,0x0e) & 0xff;
  353.     if(i==0xb6) {
  354.         model=1;            /* portable      */
  355.     asy[dev].ad